package com.zouxw.utils.json.view;

import com.zouxw.utils.json.model.JsonNode;
import com.zouxw.utils.json.utils.AppConfig;
import com.zouxw.utils.json.utils.TreeExpansionUtil;

import javax.swing.*;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeCellRenderer;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Enumeration;
import java.util.regex.Pattern;

/**
 * JSON树形视图组件
 * 负责显示JSON数据的树形结构
 * 
 * @author zouxw
 * @version 1.0
 */
public class JsonTreeView extends JScrollPane {
    
    // ==================== 组件 ====================
    /** 树形组件 */
    private JTree tree;
    
    /** 树模型 */
    private DefaultTreeModel treeModel;
    
    /** 右键菜单 */
    private JPopupMenu popupMenu;
    
    /** 添加属性菜单项 */
    private JMenuItem addPropertyMenuItem;
    
    /** 添加数组元素菜单项 */
    private JMenuItem addArrayItemMenuItem;
    
    /** 删除菜单项 */
    private JMenuItem deleteMenuItem;
    
    // ==================== 事件监听器 ====================
    /** 双击事件监听器 */
    private TreeDoubleClickListener doubleClickListener;
    
    /** 右键菜单事件监听器 */
    private TreePopupMenuListener popupMenuListener;
    
    /** 选择变化监听器 */
    private TreeSelectionListener selectionListener;
    
    // ==================== 构造函数 ====================
    
    /**
     * 构造函数
     */
    public JsonTreeView() {
        initializeComponents();
        setupEventListeners();
        setupLayout();
    }
    
    // ==================== 初始化方法 ====================
    
    /**
     * 初始化组件
     */
    private void initializeComponents() {
        // 创建树形组件
        tree = new JTree();
        tree.setFont(AppConfig.TREE_FONT);
        tree.setCellRenderer(new JsonTreeCellRenderer());
        tree.setRootVisible(false);
        tree.setShowsRootHandles(true);
        
        // 创建右键菜单
        createPopupMenu();
        
        // 设置滚动面板
        setViewportView(tree);
        setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
    }
    
    /**
     * 创建右键菜单
     */
    private void createPopupMenu() {
        popupMenu = new JPopupMenu();
        
        addPropertyMenuItem = new JMenuItem(AppConfig.POPUP_ADD_PROPERTY);
        addArrayItemMenuItem = new JMenuItem(AppConfig.POPUP_ADD_ARRAY_ITEM);
        deleteMenuItem = new JMenuItem(AppConfig.POPUP_DELETE);
        
        popupMenu.add(addPropertyMenuItem);
        popupMenu.add(addArrayItemMenuItem);
        popupMenu.addSeparator();
        popupMenu.add(deleteMenuItem);
    }
    
    /**
     * 设置事件监听器
     */
    private void setupEventListeners() {
        // 双击事件监听器
        tree.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() == 2 && doubleClickListener != null) {
                    TreePath path = tree.getPathForLocation(e.getX(), e.getY());
                    if (path != null) {
                        Object lastPathComponent = path.getLastPathComponent();
                        if (lastPathComponent instanceof JsonNode) {
                            JsonNode node = (JsonNode) lastPathComponent;
                            if (node.isLeaf()) {
                                doubleClickListener.onDoubleClick(node, path);
                            }
                        }
                    }
                }
            }
        });
        
        // 右键菜单事件监听器
        tree.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                maybeShowPopup(e);
            }
            
            @Override
            public void mouseReleased(MouseEvent e) {
                maybeShowPopup(e);
            }
            
            private void maybeShowPopup(MouseEvent e) {
                if (e.isPopupTrigger() && popupMenuListener != null) {
                    TreePath path = tree.getPathForLocation(e.getX(), e.getY());
                    if (path != null) {
                        tree.setSelectionPath(path);
                        Object lastPathComponent = path.getLastPathComponent();
                        if (lastPathComponent instanceof JsonNode) {
                            JsonNode node = (JsonNode) lastPathComponent;
                            popupMenuListener.onPopupMenuRequested(node, path, e.getX(), e.getY());
                        }
                    }
                }
            }
        });
        
        // 选择变化监听器
        tree.addTreeSelectionListener(e -> {
            if (selectionListener != null) {
                TreePath path = e.getPath();
                if (path != null) {
                    Object lastPathComponent = path.getLastPathComponent();
                    if (lastPathComponent instanceof JsonNode) {
                        JsonNode node = (JsonNode) lastPathComponent;
                        selectionListener.onSelectionChanged(node, path);
                    }
                }
            }
        });
        
        // 菜单项事件监听器
        addPropertyMenuItem.addActionListener(e -> {
            if (popupMenuListener != null) {
                TreePath selectionPath = tree.getSelectionPath();
                if (selectionPath != null) {
                    Object lastPathComponent = selectionPath.getLastPathComponent();
                    if (lastPathComponent instanceof JsonNode) {
                        JsonNode node = (JsonNode) lastPathComponent;
                        popupMenuListener.onAddPropertyRequested(node, selectionPath);
                    }
                }
            }
        });
        
        addArrayItemMenuItem.addActionListener(e -> {
            if (popupMenuListener != null) {
                TreePath selectionPath = tree.getSelectionPath();
                if (selectionPath != null) {
                    Object lastPathComponent = selectionPath.getLastPathComponent();
                    if (lastPathComponent instanceof JsonNode) {
                        JsonNode node = (JsonNode) lastPathComponent;
                        popupMenuListener.onAddArrayItemRequested(node, selectionPath);
                    }
                }
            }
        });
        
        deleteMenuItem.addActionListener(e -> {
            if (popupMenuListener != null) {
                TreePath selectionPath = tree.getSelectionPath();
                if (selectionPath != null) {
                    Object lastPathComponent = selectionPath.getLastPathComponent();
                    if (lastPathComponent instanceof JsonNode) {
                        JsonNode node = (JsonNode) lastPathComponent;
                        popupMenuListener.onDeleteRequested(node, selectionPath);
                    }
                }
            }
        });
    }
    
    /**
     * 设置布局
     */
    private void setupLayout() {
        // 布局已在构造函数中设置
    }
    
    // ==================== 公共方法 ====================
    
    /**
     * 设置树模型
     * 
     * @param treeModel 树模型
     */
    public void setTreeModel(DefaultTreeModel treeModel) {
        this.treeModel = treeModel;
        tree.setModel(treeModel);
    }
    
    /**
     * 获取树模型
     * 
     * @return 树模型
     */
    public DefaultTreeModel getTreeModel() {
        return treeModel;
    }
    
    /**
     * 展开所有节点（使用优化算法）
     */
    public void expandAllNodes() {
        TreeExpansionUtil.expandAllNodes(tree);
    }
    
    /**
     * 折叠所有节点（使用优化算法）
     */
    public void collapseAllNodes() {
        TreeExpansionUtil.collapseAllNodes(tree);
    }

    /**
     * 刷新树显示
     */
    public void refreshTree() {
        if (treeModel != null) {
            treeModel.reload();
            tree.repaint();
        }
    }

    /**
     * 获取树组件
     * 
     * @return JTree组件
     */
    public JTree getTree() {
        return tree;
    }
    
    /**
     * 搜索并高亮节点
     * 
     * @param searchText 搜索文本
     * @return 是否找到匹配项
     */
    public boolean searchAndHighlight(String searchText) {
        if (treeModel == null || searchText == null || searchText.trim().isEmpty()) {
            return false;
        }
        
        // 清除之前的高亮
        clearHighlight();
        
        // 搜索匹配的节点
        boolean found = false;
        Pattern pattern = Pattern.compile(Pattern.quote(searchText), Pattern.CASE_INSENSITIVE);
        
        Enumeration<?> enumeration = ((DefaultMutableTreeNode) treeModel.getRoot()).depthFirstEnumeration();
        while (enumeration.hasMoreElements()) {
            Object node = enumeration.nextElement();
            if (node instanceof JsonNode) {
                JsonNode jsonNode = (JsonNode) node;
                if (pattern.matcher(jsonNode.toString()).find()) {
                    jsonNode.setHighlighted(true);
                    found = true;
                    
                    // 展开到该节点
                    TreePath path = new TreePath(jsonNode.getPath());
                    tree.expandPath(path);
                    
                    // 滚动到该节点
                    tree.scrollPathToVisible(path);
                }
            }
        }
        
        // 刷新显示
        tree.repaint();
        return found;
    }
    
    /**
     * 清除高亮
     */
    public void clearHighlight() {
        if (treeModel == null) return;
        
        Enumeration<?> enumeration = ((DefaultMutableTreeNode) treeModel.getRoot()).depthFirstEnumeration();
        while (enumeration.hasMoreElements()) {
            Object node = enumeration.nextElement();
            if (node instanceof JsonNode) {
                ((JsonNode) node).setHighlighted(false);
            }
        }
        
        tree.repaint();
    }
    
    /**
     * 更新节点显示
     * 
     * @param node 节点
     */
    public void updateNode(JsonNode node) {
        if (treeModel != null) {
            treeModel.nodeChanged(node);
        }
    }
    
    /**
     * 获取选中的节点
     * 
     * @return 选中的节点
     */
    public JsonNode getSelectedNode() {
        TreePath selectionPath = tree.getSelectionPath();
        if (selectionPath != null) {
            Object lastPathComponent = selectionPath.getLastPathComponent();
            if (lastPathComponent instanceof JsonNode) {
                return (JsonNode) lastPathComponent;
            }
        }
        return null;
    }
    
    /**
     * 获取选中的路径
     * 
     * @return 选中的路径
     */
    public TreePath getSelectedPath() {
        return tree.getSelectionPath();
    }
    
    /**
     * 设置双击事件监听器
     * 
     * @param listener 监听器
     */
    public void setDoubleClickListener(TreeDoubleClickListener listener) {
        this.doubleClickListener = listener;
    }
    
    /**
     * 设置右键菜单事件监听器
     * 
     * @param listener 监听器
     */
    public void setPopupMenuListener(TreePopupMenuListener listener) {
        this.popupMenuListener = listener;
    }
    
    /**
     * 设置选择变化监听器
     * 
     * @param listener 监听器
     */
    public void setSelectionListener(TreeSelectionListener listener) {
        this.selectionListener = listener;
    }
    
    // ==================== 私有辅助方法 ====================
    
    
    // ==================== 事件监听器接口 ====================
    
    /**
     * 双击事件监听器接口
     */
    public interface TreeDoubleClickListener {
        void onDoubleClick(JsonNode node, TreePath path);
    }
    
    /**
     * 右键菜单事件监听器接口
     */
    public interface TreePopupMenuListener {
        void onPopupMenuRequested(JsonNode node, TreePath path, int x, int y);
        void onAddPropertyRequested(JsonNode node, TreePath path);
        void onAddArrayItemRequested(JsonNode node, TreePath path);
        void onDeleteRequested(JsonNode node, TreePath path);
    }
    
    /**
     * 选择变化监听器接口
     */
    public interface TreeSelectionListener {
        void onSelectionChanged(JsonNode node, TreePath path);
    }
    
    // ==================== 内部类 ====================
    
    /**
     * JSON树单元格渲染器
     */
    private static class JsonTreeCellRenderer implements TreeCellRenderer {
        private final JLabel label = new JLabel();
        
        public JsonTreeCellRenderer() {
            label.setOpaque(true);
            label.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
        }
        
        @Override
        public Component getTreeCellRendererComponent(JTree tree, Object value,
                                                      boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
            if (value instanceof JsonNode) {
                JsonNode node = (JsonNode) value;
                
                // 设置文本
                label.setText(node.toString());
                
                // 设置图标
                setIconForNodeType(node);
                
                // 设置高亮
                if (node.isHighlighted()) {
                    label.setBackground(AppConfig.SEARCH_HIGHLIGHT_COLOR);
                    label.setForeground(Color.BLACK);
                    label.setBorder(BorderFactory.createLineBorder(AppConfig.SEARCH_BORDER_COLOR, 1));
                } else if (selected) {
                    label.setBackground(UIManager.getColor("Tree.selectionBackground"));
                    label.setForeground(UIManager.getColor("Tree.selectionForeground"));
                } else {
                    label.setBackground(UIManager.getColor("Tree.textBackground"));
                    label.setForeground(UIManager.getColor("Tree.textForeground"));
                }
            } else {
                label.setText(value.toString());
                label.setIcon(null);
                
                if (selected) {
                    label.setBackground(UIManager.getColor("Tree.selectionBackground"));
                    label.setForeground(UIManager.getColor("Tree.selectionForeground"));
                } else {
                    label.setBackground(UIManager.getColor("Tree.textBackground"));
                    label.setForeground(UIManager.getColor("Tree.textForeground"));
                }
            }
            
            return label;
        }
        
        /**
         * 根据节点类型设置图标
         * 
         * @param node 节点
         */
        private void setIconForNodeType(JsonNode node) {
            String valueType = node.getValueType();
            
            if (JsonNode.VALUE_TYPE_OBJECT.equals(valueType)) {
                label.setIcon(createIcon(AppConfig.OBJECT_ICON_COLOR, 'O'));
            } else if (JsonNode.VALUE_TYPE_ARRAY.equals(valueType)) {
                label.setIcon(createIcon(AppConfig.ARRAY_ICON_COLOR, 'A'));
            } else if (JsonNode.VALUE_TYPE_STRING.equals(valueType)) {
                label.setIcon(createIcon(AppConfig.STRING_ICON_COLOR, 'S'));
            } else if (JsonNode.VALUE_TYPE_NUMBER.equals(valueType)) {
                label.setIcon(createIcon(AppConfig.NUMBER_ICON_COLOR, 'N'));
            } else if (JsonNode.VALUE_TYPE_BOOLEAN.equals(valueType)) {
                label.setIcon(createIcon(AppConfig.BOOLEAN_ICON_COLOR, 'B'));
            } else if (JsonNode.VALUE_TYPE_NULL.equals(valueType)) {
                label.setIcon(createIcon(AppConfig.NULL_ICON_COLOR, '∅'));
            } else if (JsonNode.VALUE_TYPE_NESTED_JSON.equals(valueType)) {
                label.setIcon(createIcon(AppConfig.NESTED_JSON_ICON_COLOR, 'J'));
            } else {
                label.setIcon(null);
            }
        }
        
        /**
         * 创建简单图标
         * 
         * @param color 颜色
         * @param letter 字母
         * @return 图标
         */
        private ImageIcon createIcon(Color color, char letter) {
            java.awt.image.BufferedImage image = new java.awt.image.BufferedImage(
                    AppConfig.ICON_SIZE, AppConfig.ICON_SIZE, java.awt.image.BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2 = image.createGraphics();
            
            g2.setColor(color);
            g2.fillOval(1, 1, AppConfig.ICON_SIZE - 2, AppConfig.ICON_SIZE - 2);
            
            g2.setColor(Color.WHITE);
            g2.setFont(new Font("SansSerif", Font.BOLD, AppConfig.ICON_FONT_SIZE));
            g2.drawString(String.valueOf(letter), 5, 13);
            
            g2.dispose();
            return new ImageIcon(image);
        }
    }
}
